1 Podsumowanie

Głównymi celami projektu było dokonanie analizy bazy danych Lego oraz stworzenie modelu potrafiącego przewidywać cechy przyszłych zestawów (w moim przypadku ceny zestawu). Początkowym krokiem było odpowiednie połączenie ze sobą tabel. W przypadku połączenia zestawów Lego z liczbą minifigurek ważne było wykorzystanie połączenia zewnętrzengo, aby nie stracić zestawów bez minifigurek, a następnie zastąpienie zerami brakujących wartości liczby minifigurek. Analizowane są przede wszystkim zestawy Lego, jednak znajduje się także kilka wykresów dotyczących części Lego. Dla rozkładów wartości zauważyłem m.in. lokalne wzniesienie przy 100 częściach Lego na wykresie gęstości. W przypadku trendów na przestrzeni lat dostrzegłem m.in. spadek liczby produkowanych zestawów na początku lat 2000 oraz brak trendu dla średniej liczby minifigurek w zestawach. Do predykcji wykorzystałem obcy zbiór danych zawierający sugerowane ceny zestawów, które będą przewidywane przy użyciu modelu stworzonego przy pomocy pakietu XGBoost. Aby przygotować dane do wykorzystania przez model, skorzystałem z pakietu vtreat. Przed treningiem modelu dokonałem analizy wartości cen zestawów jak i ich zależności z rokiem, liczbą części i liczbą minifigurek. W każdym przypadku widoczna była dodatnia korelacja. Ostatecznie model uzyskał wartość RMSE równą 33.551, a uzyskane przewidywania zostały przedstawione w tabeli i na wykresie.

2 Wczytanie bibliotek i globalna konfiguracja

library(dplyr)
library(tidyr)
library(ggplot2)
library(knitr)
library(plotly)
library(xgboost)
library(vtreat)
library(DT)

opts_chunk$set(echo=FALSE)
set.seed(23)

3 Wczytanie danych

inventories <- read.csv("data/inventories.csv")
inventory_parts <- read.csv("data/inventory_parts.csv")
parts <- read.csv("data/parts.csv")
colors <- read.csv("data/colors.csv")
part_categories <- read.csv("data/part_categories.csv")
elements <- read.csv("data/elements.csv")
part_relationships <- read.csv("data/part_relationships.csv")
inventory_minifigs <- read.csv("data/inventory_minifigs.csv")
minifigs <- read.csv("data/minifigs.csv")
inventory_sets <- read.csv("data/inventory_sets.csv")
sets <- read.csv("data/sets.csv")
themes <- read.csv("data/themes.csv")

W celu przyspieszenia obliczeń, blok ten jest cachowany.

4 Przegląd tabel pochodzących ze strony Rebrickable

4.1 Tabela inventories

Przykładowe wartości:

id version set_num
1 1 7922-1
3 1 3931-1
4 1 6942-1
15 1 5158-1
16 1 903-1
17 1 850950-1

Podsumowanie tabeli:

##        id            version         set_num         
##  Min.   :     1   Min.   : 1.000   Length:37265      
##  1st Qu.: 14424   1st Qu.: 1.000   Class :character  
##  Median : 54379   Median : 1.000   Mode  :character  
##  Mean   : 61104   Mean   : 1.091                     
##  3rd Qu.: 88842   3rd Qu.: 1.000                     
##  Max.   :194312   Max.   :16.000

4.2 Tabela inventory_parts

Przykładowe wartości:

inventory_id part_num color_id quantity is_spare img_url
1 48379c01 72 1 f https://cdn.rebrickable.com/media/parts/photos/1/48379c01-1-e7daa845-2671-4737-8642-3b1574308155.jpg
1 48395 7 1 f https://cdn.rebrickable.com/media/parts/photos/7/48395-7-b9152acf-2fa5-4836-a04d-5b7fd39c2406.jpg
1 stickerupn0077 9999 1 f
1 upn0342 0 1 f
1 upn0350 25 1 f
3 2343 47 1 f https://cdn.rebrickable.com/media/parts/elements/3000240.jpg

Podsumowanie tabeli:

##   inventory_id      part_num            color_id         quantity      
##  Min.   :     1   Length:1180987     Min.   :  -1.0   Min.   :   1.00  
##  1st Qu.:  9404   Class :character   1st Qu.:   4.0   1st Qu.:   1.00  
##  Median : 22838   Mode  :character   Median :  15.0   Median :   2.00  
##  Mean   : 50849                      Mean   : 131.8   Mean   :   3.37  
##  3rd Qu.: 87088                      3rd Qu.:  71.0   3rd Qu.:   4.00  
##  Max.   :194312                      Max.   :9999.0   Max.   :3064.00  
##    is_spare           img_url         
##  Length:1180987     Length:1180987    
##  Class :character   Class :character  
##  Mode  :character   Mode  :character  
##                                       
##                                       
## 

4.3 Tabela parts

Przykładowe wartości:

part_num name part_cat_id part_material
003381 Sticker Sheet for Set 663-1 58 Plastic
003383 Sticker Sheet for Sets 618-1, 628-2 58 Plastic
003402 Sticker Sheet for Sets 310-3, 311-1, 312-3 58 Plastic
003429 Sticker Sheet for Set 1550-1 58 Plastic
003432 Sticker Sheet for Sets 357-1, 355-1, 940-1 58 Plastic
003434 Sticker Sheet for Set 575-2, 653-1, 460-1 58 Plastic

Podsumowanie tabeli:

##    part_num             name            part_cat_id    part_material     
##  Length:52615       Length:52615       Min.   : 1.00   Length:52615      
##  Class :character   Class :character   1st Qu.:17.00   Class :character  
##  Mode  :character   Mode  :character   Median :41.00   Mode  :character  
##                                        Mean   :38.91                     
##                                        3rd Qu.:60.00                     
##                                        Max.   :68.00

4.4 Tabela colors

Przykładowe wartości:

id name rgb is_trans
-1 [Unknown] 0033B2 f
0 Black 05131D f
1 Blue 0055BF f
2 Green 237841 f
3 Dark Turquoise 008F9B f
4 Red C91A09 f

Podsumowanie tabeli:

##        id             name               rgb              is_trans        
##  Min.   :  -1.0   Length:263         Length:263         Length:263        
##  1st Qu.:  83.0   Class :character   Class :character   Class :character  
##  Median :1005.0   Mode  :character   Mode  :character   Mode  :character  
##  Mean   : 651.4                                                           
##  3rd Qu.:1070.5                                                           
##  Max.   :9999.0

4.5 Tabela part_categories

Przykładowe wartości:

id name
1 Baseplates
3 Bricks Sloped
4 Duplo, Quatro and Primo
5 Bricks Special
6 Bricks Wedged
7 Containers

Podsumowanie tabeli:

##        id            name          
##  Min.   : 1.00   Length:66         
##  1st Qu.:19.25   Class :character  
##  Median :35.50   Mode  :character  
##  Mean   :35.36                     
##  3rd Qu.:51.75                     
##  Max.   :68.00

4.6 Tabela elements

Przykładowe wartości:

element_id part_num color_id design_id
6443403 2277c01pr0009 1 2277
6300211 67906c01 14 67908
4566309 2564 0 2564
4275423 53657 1004 53657
6194308 92926 71 28967
6229123 26561 4 26561

Podsumowanie tabeli:

##    element_id         part_num            color_id        design_id     
##  Min.   :    9327   Length:84138       Min.   :  -1.0   Min.   :  1001  
##  1st Qu.: 4259774   Class :character   1st Qu.:   8.0   1st Qu.: 18454  
##  Median : 6057754   Mode  :character   Median :  28.0   Median : 41748  
##  Mean   : 5222065                      Mean   : 539.7   Mean   : 45570  
##  3rd Qu.: 6262024                      3rd Qu.: 135.0   3rd Qu.: 75475  
##  Max.   :61532443                      Max.   :9999.0   Max.   :107520  
##                                                         NA's   :23682

4.7 Tabela part_relationships

Przykładowe wartości:

rel_type child_part_num parent_part_num
P 3626cpr3662 3626c
P 87079pr9974 87079
P 3960pr9971 3960
R 98653pr0003 98086pr0003
R 98653pr0003 98088pat0003
R 98653pr0003 98089pat0003

Podsumowanie tabeli:

##    rel_type         child_part_num     parent_part_num   
##  Length:29977       Length:29977       Length:29977      
##  Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character

4.8 Tabela inventory_minifigs

Przykładowe wartości:

inventory_id fig_num quantity
3 fig-001549 1
4 fig-000764 1
19 fig-000555 1
25 fig-000574 1
26 fig-000842 1
26 fig-008641 1

Podsumowanie tabeli:

##   inventory_id      fig_num             quantity      
##  Min.   :     3   Length:20858       Min.   :  1.000  
##  1st Qu.:  7869   Class :character   1st Qu.:  1.000  
##  Median : 15681   Mode  :character   Median :  1.000  
##  Mean   : 43010                      Mean   :  1.062  
##  3rd Qu.: 66834                      3rd Qu.:  1.000  
##  Max.   :194312                      Max.   :100.000

4.9 Tabela minifigs

Przykładowe wartości:

fig_num name num_parts img_url
fig-000001 Toy Store Employee 4 https://cdn.rebrickable.com/media/sets/fig-000001.jpg
fig-000002 Customer Kid 4 https://cdn.rebrickable.com/media/sets/fig-000002.jpg
fig-000003 Assassin Droid, White 8 https://cdn.rebrickable.com/media/sets/fig-000003.jpg
fig-000004 Man, White Torso, Black Legs, Brown Hair 4 https://cdn.rebrickable.com/media/sets/fig-000004.jpg
fig-000005 Captain America with Short Legs 3 https://cdn.rebrickable.com/media/sets/fig-000005.jpg
fig-000006 Lloyd Avatar 5 https://cdn.rebrickable.com/media/sets/fig-000006.jpg

Podsumowanie tabeli:

##    fig_num              name             num_parts         img_url         
##  Length:13764       Length:13764       Min.   :  0.000   Length:13764      
##  Class :character   Class :character   1st Qu.:  4.000   Class :character  
##  Mode  :character   Mode  :character   Median :  4.000   Mode  :character  
##                                        Mean   :  5.296                     
##                                        3rd Qu.:  5.000                     
##                                        Max.   :156.000

4.10 Tabela inventory_sets

Przykładowe wartości:

inventory_id set_num quantity
35 75911-1 1
35 75912-1 1
39 75048-1 1
39 75053-1 1
50 4515-1 1
50 4520-1 2

Podsumowanie tabeli:

##   inventory_id      set_num             quantity     
##  Min.   :    35   Length:4358        Min.   : 1.000  
##  1st Qu.:  8076   Class :character   1st Qu.: 1.000  
##  Median : 16423   Mode  :character   Median : 1.000  
##  Mean   : 52519                      Mean   : 1.813  
##  3rd Qu.: 98685                      3rd Qu.: 1.000  
##  Max.   :191576                      Max.   :60.000

4.11 Tabela sets

Przykładowe wartości:

set_num name year theme_id num_parts img_url
001-1 Gears 1965 1 43 https://cdn.rebrickable.com/media/sets/001-1.jpg
0011-2 Town Mini-Figures 1979 67 12 https://cdn.rebrickable.com/media/sets/0011-2.jpg
0011-3 Castle 2 for 1 Bonus Offer 1987 199 0 https://cdn.rebrickable.com/media/sets/0011-3.jpg
0012-1 Space Mini-Figures 1979 143 12 https://cdn.rebrickable.com/media/sets/0012-1.jpg
0013-1 Space Mini-Figures 1979 143 12 https://cdn.rebrickable.com/media/sets/0013-1.jpg
0014-1 Space Mini-Figures 1979 143 2 https://cdn.rebrickable.com/media/sets/0014-1.jpg

Podsumowanie tabeli:

##    set_num              name                year         theme_id  
##  Length:21880       Length:21880       Min.   :1949   Min.   :  1  
##  Class :character   Class :character   1st Qu.:2001   1st Qu.:273  
##  Mode  :character   Mode  :character   Median :2012   Median :497  
##                                        Mean   :2008   Mean   :442  
##                                        3rd Qu.:2018   3rd Qu.:608  
##                                        Max.   :2024   Max.   :752  
##    num_parts         img_url         
##  Min.   :    0.0   Length:21880      
##  1st Qu.:    3.0   Class :character  
##  Median :   31.0   Mode  :character  
##  Mean   :  161.4                     
##  3rd Qu.:  139.0                     
##  Max.   :11695.0

4.12 Tabela themes

Przykładowe wartości:

id name parent_id
1 Technic NA
3 Competition 1
4 Expert Builder 1
16 RoboRiders 1
17 Speed Slammers 1
18 Star Wars 1

Podsumowanie tabeli:

##        id            name             parent_id    
##  Min.   :  1.0   Length:468         Min.   :  1.0  
##  1st Qu.:250.5   Class :character   1st Qu.:186.0  
##  Median :466.0   Mode  :character   Median :411.0  
##  Mean   :433.5                      Mean   :360.6  
##  3rd Qu.:625.2                      3rd Qu.:512.5  
##  Max.   :752.0                      Max.   :697.0  
##                                     NA's   :145

5 Utworzenie zbiorów danych do analizy

5.1 Uzyskanie informacji o głównym motywie dla każdego motywu

id name parent_id main_theme root_id
1 Technic NA Technic NA
3 Competition 1 Technic NA
4 Expert Builder 1 Technic NA
16 RoboRiders 1 Technic NA
17 Speed Slammers 1 Technic NA
18 Star Wars 1 Technic NA

Ze względu na bardzo dużą liczbę motywów, które mogą mieć zestawy Lego, postanowiłem ograniczyć się jedynie do motywów głównych. Aby tego dokonać, dla każdego istniejącego motywu odnajdywany i dodawany jest odpowiedni motyw główny. W ten sposób liczba motywów ograniczyła się z 385 unikalnych motywów do 145 głównych motywów. Nowo utworzony zbiór danych nosi nazwę ‘main_themes’ i jej przykładowe wartości prezentuje powyższa tabela.

5.2 Powiązanie tabeli nadrzędnej z zestawami i głównym motywem

id set_num version name year num_parts theme
30012 42092-1 1 Rescue Helicopter 2019 325 Technic
143628 42096-1 2 Porsche 911 RSR 2019 1580 Technic
122865 42129-1 2 4x4 Mercedes-Benz Zetros Trial Truck 2021 2131 Technic
803 8680-1 1 Arctic Rescue Base 1986 527 Technic
30011 42091-1 1 Police Pursuit 2019 120 Technic
36664 42097-1 1 Compact Crawler Crane 2019 920 Technic

Następnie tabele ‘inventories’ i ‘sets’ łączone są ze sobą wewnętrznie w wyniku czego tracona jest część danych z tabeli ‘inventories’. Utracone wiersze prezentują jednak jedynie pojedyncze minifigurki, dlatego postanowiłem nie uwzględniać tych danych w analizie. Poźniej nowo utworzony zbiór danych jest łączony ze zbiorem ‘main_themes’. Ponadto ograniczyłem liczbę kolumn do: ‘id’, ‘set_num’, ‘version’, ‘name’ (wcześniej ‘name.x’), ‘year’, ‘num_parts’, ‘theme’ (wcześniej ‘main_theme’) oraz zmieniłem typ zmiennej ‘theme’ na typ kategorialny. Ostatecznie powstaje zbiór danych ‘lego_sets’ i jej przykładowe wartości prezentuje powyższa tabela.

5.3 Dodanie informacji o liczbie minifigurek

id set_num version name year num_parts theme minifigs_count
1 7922-1 1 McDonald’s Sports Set Number 6 - Orange Vest Snowboarder 2004 5 Sports 0
3 3931-1 1 Emma’s Splash Pool 2012 43 Friends 1
4 6942-1 1 Zo Weevil 1999 20 Space 1
15 5158-1 1 T-Junction, Circle Plates 1990 2 Service Packs 0
16 903-1 1 Train Wheels and Couplers 1969 10 System 0
17 850950-1 1 Christmas Cat Ornament 2014 34 Seasonal 0

W ostatnim kroku dodane zostają informacje o liczbie minifigurek w każdym zestawie. Nie każdy zestaw posiada minifigurki, dlatego wykorzystałem połączenie zewnętrzne. Brakujące wartości zostały zastąpione zerami. W powyższej tabeli znajdują się przykładowe wartości.

Podsumowanie uzyskanego zbioru danych ‘lego_sets’:

##        id           set_num             version           name          
##  Min.   :     1   Length:23501       Min.   : 1.000   Length:23501      
##  1st Qu.:  9125   Class :character   1st Qu.: 1.000   Class :character  
##  Median : 24621   Mode  :character   Median : 1.000   Mode  :character  
##  Mean   : 51747                      Mean   : 1.144                     
##  3rd Qu.: 92840                      3rd Qu.: 1.000                     
##  Max.   :194312                      Max.   :16.000                     
##                                                                         
##       year        num_parts                         theme      
##  Min.   :1949   Min.   :    0.0   Gear                 : 3277  
##  1st Qu.:2000   1st Qu.:    3.0   Duplo                : 1417  
##  Median :2012   Median :   33.0   Educational and Dacta: 1078  
##  Mean   :2006   Mean   :  167.4   Star Wars            : 1002  
##  3rd Qu.:2018   3rd Qu.:  144.0   Books                :  999  
##  Max.   :2024   Max.   :11695.0   System               :  972  
##                                   (Other)              :14756  
##  minifigs_count    
##  Min.   :  0.0000  
##  1st Qu.:  0.0000  
##  Median :  0.0000  
##  Mean   :  0.9425  
##  3rd Qu.:  1.0000  
##  Max.   :100.0000  
## 

5.4 Powiązanie części Lego z ich kolorem i kategorią

inventory_id quantity is_spare color rgb is_trans part_material category
10813 1 FALSE Dark Gray 6D6E5C FALSE Plastic Baseplates
8694 1 FALSE Light Gray 9BA19D FALSE Plastic Baseplates
7239 1 FALSE Green 237841 FALSE Plastic Baseplates
103713 2 FALSE Green 237841 FALSE Plastic Baseplates
14142 1 FALSE Dark Bluish Gray 6C6E68 FALSE Plastic Baseplates
2796 1 FALSE Blue 0055BF FALSE Plastic Baseplates

Dodatkowo dla analizy skoncetrowanej na częściach Lego, połączyłem tabele ‘inventory_parts’, ‘colors’ i ‘part_categories’ tworząc wynikowy zbiór danych ‘lego_parts’, którego przykładowe wartości widoczne są w powyższej tabeli. Ograniczyłem liczbę kolumn do: ‘inventory_id’, ‘quantity’, ‘is_spare’, ‘color’ (wcześniej ‘name.x’), ‘rgb’, ‘is_trans’, ‘part_material’, ‘category’ (wcześniej ‘name’). Zmieniłem typy zmiennych ‘category’, ‘part_material’ i ‘color’ na typy kategorialne. Z kolei zmienne ‘is_trans’ i ‘is_spare’ stały się zmiennymi logicznymi.

Podsumowanie uzyskanego zbioru danych ‘lego_parts’:

##   inventory_id       quantity        is_spare                     color       
##  Min.   :     1   Min.   :   1.00   Mode :logical   Black            :208830  
##  1st Qu.:  9404   1st Qu.:   1.00   FALSE:1104122   White            :133815  
##  Median : 22838   Median :   2.00   TRUE :76865     Light Bluish Gray:123665  
##  Mean   : 50849   Mean   :   3.37                   Dark Bluish Gray : 92073  
##  3rd Qu.: 87088   3rd Qu.:   4.00                   Red              : 88780  
##  Max.   :194312   Max.   :3064.00                   Yellow           : 66197  
##                                                     (Other)          :467627  
##      rgb             is_trans                part_material    
##  Length:1180987     Mode :logical   Cardboard/Paper :   2367  
##  Class :character   FALSE:1113125   Cloth           :   2029  
##  Mode  :character   TRUE :67862     Flexible Plastic:    245  
##                                     Foam            :     67  
##                                     Metal           :    101  
##                                     Plastic         :1167738  
##                                     Rubber          :   8440  
##                            category     
##  Plates                        :160931  
##  Bricks                        : 92632  
##  Plates Special                : 91303  
##  Bricks Sloped                 : 68583  
##  Tiles                         : 60663  
##  Plates Round Curved and Dishes: 56183  
##  (Other)                       :650692

6 Analiza zestawów Lego

6.1 Rozkłady wartości

Z wykresu ciężko coś odczytać ze względu na dużą liczbę odstających wartości oraz skoncentrowanie danych w okolicach zera. Z tego względu postanowiłem pozbyć się wartości najbardziej odstających:

quartiles <- quantile(lego_sets$num_parts, probs=c(.25, .75))
IQR <- IQR(lego_sets$num_parts)
 
Lower <- quartiles[1] - 1.5*IQR
Upper <- quartiles[2] + 1.5*IQR 
 
lego_sets_num_parts_no_outliers <- subset(lego_sets, lego_sets$num_parts > Lower & lego_sets$num_parts < Upper)

Kolejne 2 wykresy przedstawiają rozkład liczby części Lego po usunięciu odstających wartości:

Z tego co widzimy na wykresie gęstości, najwięcej zestawów składa się tylko z jednej części. W miarę zwiększania się liczby części, wartość funkcji gęstości maleje. Wyjątkiem tutaj jest wzniesienie przy około 100 częściach co oznacza, że powstaje stosunkowo dużo zestawów z taką liczbą części. Podobne wzniesienie można zaobserwować również w okolicach liczby 200, lecz jest ono znacznie mniejsze.

Powyższy wykres został ograniczony do zestawów, które posiadają przynajmniej jedną minifigurkę.

Przeważająca większość zestawów posiada tylko jedną wersję, lecz mimo to zauważalna ilość powstaje w więcej niż jednej wersji.

6.2 Rankingi

Ponieważ liczba części ma bardzo dużo wartości odstających o wysokich wartościach, zdecydowałem się na wykorzystanie mediany, ponieważ jest ona bardziej odporna od średniej na wartości odstające.

6.3 Trendy na przestrzeni lat

Na wykresie widać gwałtowny wzrost produkowanych zestawów od końcówki lat 90, a następnie spadek od roku 2002 do 2005. Prawdopodobnie jest to powiązane z kryzysem firmy w tamtym czasie i drastycznymi cięciami kosztów: https://businessinsider.com.pl/firmy/strategie/lego-model-biznesowy-i-strategia-vidiyo-zestawy-hidden-side-nowe-produkty-i-historia/4zzgq1x

Pierwsze minifigurki Lego zaczęły pojawiać się w zestawach od około 1975 roku i od tego czasu ich średnia liczba nie ma trendu rosnącego ani spadkowego. Widać to wyraźniej na wykresie poniżej, który uwzględnia jedynie zestawy z przynajmniej jedną minifigurką:

6.4 Zależności

Wraz z pojawieniem się minifigurek Lego, stosunkowa ilość zestawów z ich udziałem rosła/malała podobnie jak zestawów bez minifigurek.

7 Analiza części Lego

8 Predykcja cen przyszłych zestawów Lego

Zbiór danych zawierający m.in nazwy zestawów i ich ceny pochodzi ze strony: https://www.kaggle.com/datasets/alexracape/lego-sets-and-prices-over-time/data

8.1 Dodanie informacji o cenach

Istniejący zbiór danych ‘lego_sets’ połączony został wewnętrznie z nowo wczytaną tabelą. Dodane zostały nowe kolumny: ‘theme_group’ (grupa tematyczna), ‘category’ (kategoria zestawu), ‘price’ (Sugerowana Cena Detaliczna Producenta w USD). Ze względu na połączenie wewnętrzne, tracona jest spora część danych - zachowujemy jedynie 6252 wierszy z 23501. Nowo powstały zbiór danych nazwany jest ‘lego_sets_with_price’ i jego wartości przedstawione są w interaktywnej tabeli poniżej:

8.2 Analiza danych

Zdecydowana większość zestawów miało cenę w wysokości około 10 dolarów. Dodatkowo dostrzec można lokalne wzniesienia funkcji gęstości co mniej więcej 50 dolarów.

W miarę zwiększania zarówno liczby części jak i liczby minifigurek, zestawy stają się średnio droższe.

8.3 Przygotowanie danych

trainData <- lego_sets_with_price[lego_sets_with_price$year < 2020,]
testData  <- lego_sets_with_price[lego_sets_with_price$year >= 2020,]

Zbiór danych podzielony został na dane treningowe i testowe. Dane treningowe to zestawy z rokiem wcześniejszym niż 2020, a pozostałe dane to dane testowe.

X <- c("year", "category", "theme_group", "theme", "num_parts", "minifigs_count")
y <- "price"
cfe <- mkCrossFrameNExperiment(trainData, varlist = X, outcomename = y, verbose = F)
plan <- cfe$treatments
summary(cfe$crossFrame)
##       year      category_catP       category_catN       category_catD    
##  Min.   :1991   Min.   :0.0006291   Min.   :-35.44865   Min.   : 0.5774  
##  1st Qu.:2010   1st Qu.:0.8860919   1st Qu.:  2.64731   1st Qu.:51.0315  
##  Median :2013   Median :0.8883297   Median :  2.86430   Median :51.9741  
##  Mean   :2013   Mean   :0.7986192   Mean   : -0.00188   Mean   :48.4188  
##  3rd Qu.:2016   3rd Qu.:0.8902170   3rd Qu.:  2.86522   3rd Qu.:52.9725  
##  Max.   :2019   Max.   :0.8902170   Max.   : 48.81031   Max.   :52.9725  
##  theme_group_catP   theme_group_catN    theme_group_catD    theme_catP       
##  Min.   :0.002202   Min.   :-22.51049   Min.   :  9.079   Min.   :0.0001573  
##  1st Qu.:0.079924   1st Qu.:-18.41115   1st Qu.: 25.929   1st Qu.:0.0116389  
##  Median :0.137823   Median : -1.61755   Median : 30.715   Median :0.0365009  
##  Mean   :0.135079   Mean   :  0.01816   Mean   : 41.249   Mean   :0.0449499  
##  3rd Qu.:0.195091   3rd Qu.: 14.48412   3rd Qu.: 67.112   3rd Qu.:0.0855615  
##  Max.   :0.221208   Max.   : 85.39680   Max.   :115.633   Max.   :0.0984896  
##    theme_catN          theme_catD       num_parts      minifigs_count   
##  Min.   :-34.65366   Min.   :  0.00   Min.   :   0.0   Min.   :  0.000  
##  1st Qu.:-14.99429   1st Qu.: 20.88   1st Qu.:  46.0   1st Qu.:  0.000  
##  Median : -6.27741   Median : 27.07   Median : 141.0   Median :  1.000  
##  Mean   : -0.07061   Mean   : 37.34   Mean   : 320.2   Mean   :  1.884  
##  3rd Qu.: 14.75405   3rd Qu.: 49.01   3rd Qu.: 379.0   3rd Qu.:  3.000  
##  Max.   :145.12827   Max.   :119.02   Max.   :7541.0   Max.   :100.000  
##  category_lev_x_Gear category_lev_x_Normal
##  Min.   :0.00000     Min.   :0.0000       
##  1st Qu.:0.00000     1st Qu.:1.0000       
##  Median :0.00000     Median :1.0000       
##  Mean   :0.09815     Mean   :0.8882       
##  3rd Qu.:0.00000     3rd Qu.:1.0000       
##  Max.   :1.00000     Max.   :1.0000       
##  theme_group_lev_x_Action_slash_Adventure theme_group_lev_x_Basic
##  Min.   :0.0000                           Min.   :0.00000        
##  1st Qu.:0.0000                           1st Qu.:0.00000        
##  Median :0.0000                           Median :0.00000        
##  Mean   :0.1191                           Mean   :0.02349        
##  3rd Qu.:0.0000                           3rd Qu.:0.00000        
##  Max.   :1.0000                           Max.   :1.00000        
##  theme_group_lev_x_Constraction theme_group_lev_x_Licensed
##  Min.   :0.00000                Min.   :0.0000            
##  1st Qu.:0.00000                1st Qu.:0.0000            
##  Median :0.00000                Median :0.0000            
##  Mean   :0.04782                Mean   :0.2158            
##  3rd Qu.:0.00000                3rd Qu.:0.0000            
##  Max.   :1.00000                Max.   :1.0000            
##  theme_group_lev_x_Miscellaneous theme_group_lev_x_Model_making
##  Min.   :0.0000                  Min.   :0.00000               
##  1st Qu.:0.0000                  1st Qu.:0.00000               
##  Median :0.0000                  Median :0.00000               
##  Mean   :0.1906                  Mean   :0.06607               
##  3rd Qu.:0.0000                  3rd Qu.:0.00000               
##  Max.   :1.0000                  Max.   :1.00000               
##  theme_group_lev_x_Modern_day theme_group_lev_x_Pre_minus_school
##  Min.   :0.0000               Min.   :0.00000                   
##  1st Qu.:0.0000               1st Qu.:0.00000                   
##  Median :0.0000               Median :0.00000                   
##  Mean   :0.1443               Mean   :0.08221                   
##  3rd Qu.:0.0000               3rd Qu.:0.00000                   
##  Max.   :1.0000               Max.   :1.00000                   
##  theme_group_lev_x_Racing theme_group_lev_x_Technical theme_lev_x_Bionicle
##  Min.   :0.00000          Min.   :0.00000             Min.   :0.00000     
##  1st Qu.:0.00000          1st Qu.:0.00000             1st Qu.:0.00000     
##  Median :0.00000          Median :0.00000             Median :0.00000     
##  Mean   :0.02118          Mean   :0.04908             Mean   :0.02789     
##  3rd Qu.:0.00000          3rd Qu.:0.00000             3rd Qu.:0.00000     
##  Max.   :1.00000          Max.   :1.00000             Max.   :1.00000     
##  theme_lev_x_City  theme_lev_x_Collectible_Minifigures theme_lev_x_Creator
##  Min.   :0.00000   Min.   :0.00000                     Min.   :0.00000    
##  1st Qu.:0.00000   1st Qu.:0.00000                     1st Qu.:0.00000    
##  Median :0.00000   Median :0.00000                     Median :0.00000    
##  Mean   :0.08997   Mean   :0.02265                     Mean   :0.04677    
##  3rd Qu.:0.00000   3rd Qu.:0.00000                     3rd Qu.:0.00000    
##  Max.   :1.00000   Max.   :1.00000                     Max.   :1.00000    
##  theme_lev_x_Duplo theme_lev_x_Friends theme_lev_x_Gear theme_lev_x_Ninjago
##  Min.   :0.00000   Min.   :0.00000     Min.   :0.0000   Min.   :0.00000    
##  1st Qu.:0.00000   1st Qu.:0.00000     1st Qu.:0.0000   1st Qu.:0.00000    
##  Median :0.00000   Median :0.00000     Median :0.0000   Median :0.00000    
##  Mean   :0.08242   Mean   :0.04677     Mean   :0.0948   Mean   :0.04677    
##  3rd Qu.:0.00000   3rd Qu.:0.00000     3rd Qu.:0.0000   3rd Qu.:0.00000    
##  Max.   :1.00000   Max.   :1.00000     Max.   :1.0000   Max.   :1.00000    
##  theme_lev_x_Seasonal theme_lev_x_Star_Wars theme_lev_x_Technic
##  Min.   :0.00000      Min.   :0.0000        Min.   :0.00000    
##  1st Qu.:0.00000      1st Qu.:0.0000        1st Qu.:0.00000    
##  Median :0.00000      Median :0.0000        Median :0.00000    
##  Mean   :0.02685      Mean   :0.0862        Mean   :0.03586    
##  3rd Qu.:0.00000      3rd Qu.:0.0000        3rd Qu.:0.00000    
##  Max.   :1.00000      Max.   :1.0000        Max.   :1.00000    
##  theme_lev_x_Racers     price       
##  Min.   :0.00000    Min.   :  1.49  
##  1st Qu.:0.00000    1st Qu.:  9.99  
##  Median :0.00000    Median : 19.99  
##  Mean   :0.02034    Mean   : 37.83  
##  3rd Qu.:0.00000    3rd Qu.: 49.99  
##  Max.   :1.00000    Max.   :849.99

Do przygotowania danych do zadania regresji wykorzystany został pakiet vtreat, który potrafi m.in zamieniać zmienne kategorialne na numeryczne lub tworzyć nowe zmienne w oparciu o istniejące (np. zmienne wpływu, zmienne zawierające częstość występowania zmiennych). Najbardziej istotne zmienne są następnie automatycznie wybierane. Podsumowanie tych zmiennych znajduje się powyżej.

8.4 Trening modelu

Jako model postanowiłem wybrać drzewa wzmacniane gradientowo, a konkretnie pakiet xgboost.

trainMatrix <- as.matrix(subset(cfe$crossFrame, select = -price))

cv <- xgb.cv(trainMatrix, label = trainData$price,
             params = list(objective = "reg:squarederror"),
             nfold = 5,
             nrounds = 100,
             print_every_n = 10)
## [1]  train-rmse:46.256207+0.741671   test-rmse:46.585969+3.642867 
## [11] train-rmse:11.436735+0.303852   test-rmse:17.191881+2.492174 
## [21] train-rmse:10.008665+0.370647   test-rmse:16.727532+2.092106 
## [31] train-rmse:9.317084+0.434719    test-rmse:16.630321+2.044780 
## [41] train-rmse:8.729246+0.425535    test-rmse:16.581071+2.064203 
## [51] train-rmse:8.310997+0.436576    test-rmse:16.575638+2.065177 
## [61] train-rmse:7.996495+0.461478    test-rmse:16.598380+2.063306 
## [71] train-rmse:7.694729+0.442138    test-rmse:16.638898+2.012000 
## [81] train-rmse:7.471597+0.455581    test-rmse:16.624840+2.019884 
## [91] train-rmse:7.293423+0.459289    test-rmse:16.648787+1.982609 
## [100]    train-rmse:7.165383+0.465258    test-rmse:16.676541+1.964070
evalframe <- as.data.frame(cv$evaluation_log)

Początkowo odbywa się faza dostrajania hiperparametru ‘nrounds’ oznaczającego liczbę tworzonych drzew. Poniżej znajduje się wykres z uzyskanymi wynikami i wybraną liczbą drzew oznaczoną niebieską linią:

model <- xgboost(data = trainMatrix,
                 label = trainData$price,
                 params = list(objective = "reg:squarederror"),
                 nrounds = NROUNDS, 
                 verbose = FALSE)
model
## ##### xgb.Booster
## raw: 146.9 Kb 
## call:
##   xgb.train(params = params, data = dtrain, nrounds = nrounds, 
##     watchlist = watchlist, verbose = verbose, print_every_n = print_every_n, 
##     early_stopping_rounds = early_stopping_rounds, maximize = maximize, 
##     save_period = save_period, save_name = save_name, xgb_model = xgb_model, 
##     callbacks = callbacks)
## params (as set within xgb.train):
##   objective = "reg:squarederror", validate_parameters = "TRUE"
## xgb.attributes:
##   niter
## callbacks:
##   cb.evaluation.log()
## # of features: 36 
## niter: 47
## nfeatures : 36 
## evaluation_log:
##     iter train_rmse
##        1  46.168412
##        2  34.793118
## ---                
##       46   8.907868
##       47   8.894319

Następnie odbywa się właściwy trening modelu z odpowiednio ustawionym parametrem ‘nrounds’.

8.5 Ocena modelu

W poniższej tabeli znajdują się wyniki predykcji modelu i wartości rzeczywiste:

Model uzyskał następujący wynik dla współczynnika RMSE:

## [1] 33.55103

RMSE można interpretować jako średnią oczekiwaną różnicę +/- między wartością przewidywaną a rzeczywistą.

Powyżej znajduje się wykres zależności między ceną rzeczywistą a przewidywaną. Mimo tego, że istnieją liczne obserwacje dla których przewidywania modelu znacznie odbiegają od rzeczywistości, to w ogólności radzi sobie on dość dobrze.